﻿@page "/Account/ResetPassword"

@using System.ComponentModel.DataAnnotations
@using System.Text
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Identity
@using Microsoft.AspNetCore.WebUtilities
@using MyApp.Data
@using MyApp.Identity

@inject IdentityRedirectManager RedirectManager
@inject UserManager<ApplicationUser> UserManager

<PageTitle>Reset password</PageTitle>

<div class="mt-8 mx-auto max-w-lg">
    <Heading1>Reset password</Heading1>
    <Heading2>Reset your password.</Heading2>

    <StatusMessage Message="@Message" />
    <div class="mt-3 shadow overflow-hidden sm:rounded-md">
        <div class="px-4 bg-white dark:bg-black sm:p-6">
            <EditForm id="reset-password-form" Model="Input" FormName="reset-password" OnValidSubmit="OnValidSubmitAsync" method="post">
                <DataAnnotationsValidator />
                <ValidationSummary class="mb-3 text-danger text-center font-semibold" />
                <input type="hidden" name="Input.Code" value="@Input.Code" />

                <div class="flex flex-col gap-y-4">
                    <div>
                        <label for="email" class="@TextInput.LabelClasses">Email</label>
                        <div class="mt-1 relative rounded-md shadow-sm">
                            <InputText id="email" type="text" @bind-Value="Input.Email" class="@TextInput.InputClasses" autocomplete="username" aria-required="true" placeholder="name@example.com" />
                        </div>
                        <ValidationMessage For="() => Input.Email" class="mt-2 text-danger text-sm" />
                    </div>
                    <div>
                        <label for="password" class="@TextInput.LabelClasses">Password</label>
                        <div class="mt-1 relative rounded-md shadow-sm">
                            <InputText id="password" type="password" @bind-Value="Input.Password" class="@TextInput.InputClasses" autocomplete="new-password" aria-required="true" placeholder="Please enter your password." />
                        </div>
                        <ValidationMessage For="() => Input.Password" class="mt-2 text-danger text-sm" />
                    </div>
                    <div>
                        <label for="confirm-password" class="@TextInput.LabelClasses">Confirm password</label>
                        <div class="mt-1 relative rounded-md shadow-sm">
                            <InputText id="confirm-password" type="password" @bind-Value="Input.ConfirmPassword" class="@TextInput.InputClasses" autocomplete="new-password" aria-required="true" placeholder="Please confirm your password." />
                        </div>
                        <ValidationMessage For="() => Input.ConfirmPassword" class="mt-2 text-danger text-sm" />
                    </div>
                    <div>
                        <PrimaryButton type="submit">Reset</PrimaryButton>
                    </div>
                </div>
            </EditForm>
        </div>
    </div>
</div>

@code {
    [SupplyParameterFromForm]
    private InputModel Input { get; set; } = new();

    [SupplyParameterFromQuery]
    private string? Code { get; set; }

    IEnumerable<IdentityError>? identityErrors;
    private string? Message => identityErrors is null ? null : "Error: " + string.Join(", ", identityErrors.Select(error => error.Description));

    protected override void OnInitialized()
    {
        if (Code is null)
        {
            RedirectManager.RedirectTo("/Account/InvalidPasswordReset");
        }
        else
        {
            Input.Code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(Code));
        }
    }

    private async Task OnValidSubmitAsync()
    {
        var user = await UserManager.FindByEmailAsync(Input.Email);
        if (user is null)
        {
            // Don't reveal that the user does not exist
            RedirectManager.RedirectTo("/Account/ResetPasswordConfirmation");
            return;
        }

        var result = await UserManager.ResetPasswordAsync(user, Input.Code, Input.Password);
        if (result.Succeeded)
        {
            RedirectManager.RedirectTo("/Account/ResetPasswordConfirmation");
            return;
        }

        identityErrors = result.Errors;
    }

    private sealed class InputModel
    {
        [Required]
        [EmailAddress]
        public string Email { get; set; } = default!;

        [Required]
        [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
        [DataType(DataType.Password)]
        public string Password { get; set; } = default!;

        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
        public string ConfirmPassword { get; set; } = default!;

        [Required]
        public string Code { get; set; } = default!;
    }
}
